home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / zip / part02 < prev    next >
Encoding:
Text File  |  1992-03-01  |  72.3 KB  |  2,402 lines

  1. Newsgroups: comp.sources.unix
  2. From: madler@cco.caltech.edu (Mark Adler)
  3. Subject: v25i143: zip - file compression/archive tool, Part02/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: madler@cco.caltech.edu (Mark Adler)
  8. Posting-Number: Volume 25, Issue 143
  9. Archive-Name: zip/part02
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 2 (of 7)."
  18. # Contents:  im_lm.asm implode.c shrink.c util.c zip.h zipnote.c
  19. #   zipup.c
  20. # Wrapped by vixie@cognition.pa.dec.com on Sun Mar  1 18:57:37 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'im_lm.asm' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'im_lm.asm'\"
  24. else
  25. echo shar: Extracting \"'im_lm.asm'\" \(9944 characters\)
  26. sed "s/^X//" >'im_lm.asm' <<'END_OF_FILE'
  27. X;
  28. X; Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  29. X; Permission is granted to any individual or institution to use, copy, or
  30. X; redistribute this software so long as all of the original files are included
  31. X; unmodified, that it is not sold for profit, and that this copyright notice
  32. X; is retained.
  33. X;
  34. X
  35. X; im_lm.asm by Jean-loup Gailly.
  36. X
  37. X;im_lm.asm, optimized version of longest_match() and lm_process() in im_lmat.c
  38. X; Must be assembled with masm -ml. To be used only with C small model or
  39. X; compact model. This file is only optional. If you don't have masm, use the
  40. X; C version (add -DNO_ASM to CFLAGS in makefile.dos and remove im_lm.obj
  41. X; from OBJI).
  42. X;
  43. X; Turbo C 2.0 does not support static allocation of far data in
  44. X; the small model. So TC 2.0 users must assemble this with:
  45. X;   tasm -ml -DDYN_ALLOC im_lm;
  46. X; OS/2 users must assemble this with -DOS2 -ml. To simplify the code,
  47. X; the option -DDYN_ALLOC is not supported for OS/2.
  48. X        name    im_lm
  49. X
  50. ifndef DYN_ALLOC
  51. X        extrn   _prev         : word
  52. X        extrn   _next         : word
  53. X        prev    equ  _prev
  54. X        next    equ  _next
  55. load_es_prev macro
  56. X        mov     cx,seg _prev
  57. X        mov     es,cx
  58. endm
  59. load_ds_next macro
  60. X        mov     si,seg _next
  61. X        mov     ds,si
  62. endm
  63. endif
  64. X
  65. X_BSS    segment  word public 'BSS'
  66. X        extrn   _window       : byte
  67. X        extrn   _match_length : word
  68. X        extrn   _start_length : word
  69. X        extrn   _strstart     : word
  70. X        extrn   _strsize      : word
  71. X        extrn   _ins_h        : word
  72. X        extrn   _h_shift      : byte
  73. X        extrn   _checkpoint   : word
  74. X        extrn   _bufsize      : word
  75. X        extrn   _max_chain_length : word
  76. X        extrn   _min_match_length : word
  77. ifdef DYN_ALLOC
  78. X        extrn   _prev         : word
  79. X        extrn   _next         : word
  80. X        prev    equ 0         ; offset normalized to zero (except for OS/2)
  81. X        next    equ 0         ; offset normalized to zero (except for OS/2)
  82. load_es_prev macro
  83. X        mov     es,_prev[2]   ; warning: the offset should be added under OS/2
  84. endm
  85. load_ds_next macro
  86. X        mov     ds,_next[2]   ; warning: the offset should be added under OS/2
  87. endm
  88. endif
  89. X        cur_best dw 1 dup(?)  ; best match within longest_match
  90. X_BSS    ends
  91. X
  92. DGROUP  group _BSS
  93. X
  94. X_TEXT   segment word public 'CODE'
  95. X        assume  cs: _TEXT, ds: DGROUP, ss: DGROUP
  96. X
  97. X        extrn   _write_match : near
  98. X
  99. X        BSZ          equ 4096           ; keep consistent with tailor.h
  100. X        WSIZE        equ 8192           ; keep consistent with im_lmat.c
  101. X        NIL          equ (WSIZE+BSZ)
  102. X        MAX_DIST     equ NIL
  103. X        MAX_LENGTH   equ 320            ; keep consistent with im_lmat.c
  104. X        HASH_MASK    equ 16383          ; (1<<14)-1
  105. X
  106. X; Process a block of characters already inserted in the window
  107. X; IN assertion: count > 0
  108. X        public _lm_process
  109. X_lm_process  proc near
  110. X        push    bp
  111. X        mov     bp,sp
  112. X        push    di
  113. X        push    si
  114. X
  115. X        count   equ word ptr [bp+4]
  116. X;       delete_point equ ax
  117. X;       ins_h        equ bx
  118. X;       h_shift      equ cl
  119. X;       count        equ dx
  120. X;       cur_match    equ si
  121. X;       strstart     equ di
  122. X;       min_match_length equ bp
  123. X
  124. X        mov     dx,count
  125. X        mov     bx,_ins_h
  126. X        mov     di,_strstart
  127. X        lea     ax,[di+MAX_LENGTH-1]
  128. X        sub     ax,_bufsize
  129. X        jae     del_ok
  130. X        add     ax,MAX_DIST
  131. del_ok: shl     ax,1                    ;delete_point as word index
  132. X        load_es_prev
  133. X        mov     cl,_h_shift
  134. X        load_ds_next
  135. X        assume  ds: nothing
  136. X        jmp     short insert
  137. X
  138. start_overflow:
  139. X        sub     di,di                   ;strstart = 0
  140. X        sub     ss:_checkpoint,MAX_DIST
  141. X        jmp     short check_count
  142. del_overflow:
  143. X        mov     ax,-2                   ;delete_point = 0
  144. main_loop:
  145. X        add     ax,2                    ;delete_point++ (word index)
  146. X        cmp     ax,2*MAX_DIST
  147. X        je      del_overflow
  148. X        xchg    ax,si                   ;si=2*delete_point
  149. X        mov     bp,next[si]
  150. X        shl     bp,1
  151. X        mov     es:prev[bp],NIL
  152. X        xchg    ax,si                   ;ax=2*delete_point
  153. X
  154. X        inc     di                      ;strstart++
  155. X        cmp     di,MAX_DIST
  156. X        je      start_overflow
  157. check_count:
  158. X        dec     dx                      ;count--
  159. X        jz      end_proc_ok
  160. insert:
  161. X        shl     bx,cl                   ;ins_h <<= h_shift
  162. X        mov     bp,ss:_min_match_length
  163. X        xor     bl,_window[di+bp-1]     ;ins_h ^= window[s+min_match_length-1]
  164. X        and     bx,HASH_MASK
  165. X        add     bx,MAX_DIST+1
  166. X        shl     bx,1                    ;word index
  167. X        mov     si,es:prev[bx]          ;cur_match = match_head[ins_h]
  168. X        mov     es:prev[bx],di          ;prev[ins_h+MAX_DIST+1] = strstart
  169. X        shr     bx,1                    ;bx = ins_h + MAX_DIST + 1
  170. X        shl     di,1                    ;di = strstart as word index
  171. X        mov     next[di],bx
  172. X        sub     bx,MAX_DIST+1           ;bx = ins_h
  173. X        mov     es:prev[di],si          ;prev[s] = cur_match
  174. X        shr     di,1                    ;di = strstart
  175. X        shl     si,1
  176. X        mov     next[si],di             ;next[cur_match] = strstart
  177. X        cmp     di,ss:_checkpoint
  178. X        jne     main_loop
  179. X
  180. X        push    ax
  181. X        push    bx
  182. X        push    dx
  183. X        mov     ax,ss
  184. X        mov     ds,ax
  185. X        assume  ds: DGROUP
  186. X        mov     _match_length,0
  187. X        mov     _strstart,di
  188. X        shr     si,1                    ;si = cur_match
  189. X        cmp     si,NIL                  ;cur_match == NIL ?
  190. X        je      call_write
  191. X        call    _longest_match          ;returns best_match in si
  192. call_write:
  193. X        push    _match_length
  194. X        push    si                      ;best_match or NIL
  195. X        call    _write_match
  196. X        add     sp,4
  197. X        pop     dx
  198. X        pop     bx
  199. X        or      al,al
  200. X        jnz     failure
  201. X        pop     ax
  202. X        load_es_prev
  203. X        mov     cl,_h_shift
  204. X        load_ds_next
  205. X        assume  ds: nothing
  206. X        jmp     main_loop
  207. end_proc_ok:
  208. X        mov     ax,ss
  209. X        mov     ds,ax
  210. X        assume  ds: DGROUP
  211. X        sub     ax,ax
  212. X        mov     _strstart,di
  213. end_proc:
  214. X        mov     _ins_h,bx
  215. X        pop     si
  216. X        pop     di
  217. X        pop     bp
  218. X        ret
  219. failure:
  220. X        add     sp,2                    ;skip pushed ax
  221. X        jmp     short end_proc
  222. X
  223. X_lm_process  endp
  224. X
  225. X; Find the longest match starting at the given string. Return its position
  226. X; and set its length in match_length. Matches shorter or equal to
  227. X; start_length are discarded, in which case match_length is unchanged
  228. X; and the result position is NIL.
  229. X; IN assertions: cur_match is the head of the hash chain for the current
  230. X;    string (strstart) and is not NIL, start_length >= 1.
  231. X;    registers: es points to the base of the prev array (preserved)
  232. X;               si = cur_match and return value
  233. X;               di = strstart
  234. X
  235. X; IPos longest_match(cur_match)
  236. X
  237. X        public _longest_match
  238. X_longest_match  proc near
  239. X
  240. X        push    bp
  241. X        push    di
  242. X
  243. X;       match        equ si
  244. X;       scan         equ di
  245. X;       chain_count  equ bp
  246. X;       ma_length    equ bx
  247. X
  248. X        lea     di,_window[di+2]        ; di = window + strstart + 2
  249. X        mov     cur_best,NIL
  250. X        mov     bp,_max_chain_length    ; chain_count = max_chain_length
  251. X        mov     bx,_start_length        ; ma_length = start_length
  252. X        mov     ax,[bx+di-3]            ; ax = scan[ma_length-1..ma_length]
  253. X        mov     cx,[di-2]               ; cx = scan[0..1]
  254. X        jmp     short do_scan
  255. X
  256. X        even                            ; align destination of branch
  257. long_loop:
  258. X; at this point, di == scan+2, si = cur_match
  259. X        mov     ax,[bx+di-3]            ; ax = scan[ma_length-1..ma_length]
  260. X        mov     cx,[di-2]               ; cx = scan[0..1]
  261. short_loop:
  262. X        dec     bp                      ; --chain_count
  263. X        jz      the_end
  264. X; at this point, di == scan+2, si = cur_match,
  265. X; ax = scan[ma_length-1..ma_length] and cx = scan[0..1]
  266. X        shl     si,1                    ; cur_match as word index
  267. X        mov     si,es:prev[si]          ; cur_match = prev[cur_match]
  268. X        cmp     si,NIL
  269. X        je      the_end
  270. do_scan:
  271. X        cmp     ax,word ptr _window[bx+si-1] ; check match at ma_length-1
  272. X        jne     short_loop
  273. X        cmp     cx,word ptr _window[si]      ; check min_match_length match
  274. X        jne     short_loop
  275. X        mov     dx,si                   ; dx = cur_match
  276. X        lea     si,_window[si+2]        ; si = match
  277. X        mov     ax,di                   ; ax = scan+2
  278. X        mov     cx,ds
  279. X        mov     es,cx
  280. X        mov     cx,(MAX_LENGTH-2)/2     ; scan for at most MAX_LENGTH bytes
  281. X        repe    cmpsw                   ; loop until mismatch
  282. X        load_es_prev                    ; reset es to address the prev array
  283. X        mov     cl,[di-2]               ; mismatch on first or second byte?
  284. X        sub     cl,[si-2]               ; dl = 0 if first bytes equal
  285. X        xchg    ax,di                   ; di = scan+2, ax = end of scan
  286. X        sub     ax,di                   ; ax = len
  287. X        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
  288. X        adc     ax,0                    ; ax = carry ? len+1 : len
  289. X        mov     si,dx                   ; si = cur_match
  290. X        cmp     ax,bx                   ; len > ma_length ?
  291. X        jle     long_loop
  292. X        mov     cur_best,si             ; cur_best = cur_match
  293. X        mov     bx,ax                   ; bx = ma_length = len
  294. X        cmp     ax,_strsize             ; len >= strsize ?
  295. X        jle     long_loop
  296. the_end:
  297. X        cmp     bx,_start_length        ; ma_length > start_length ?
  298. X        jle     return
  299. X        mov     _match_length,bx        ; match_length = ma_length
  300. return:
  301. X        mov     si,cur_best             ; result = cur_best
  302. X        pop     di
  303. X        pop     bp
  304. X        ret
  305. X
  306. X_longest_match  endp
  307. X
  308. X_TEXT   ends
  309. end
  310. END_OF_FILE
  311. if test 9944 -ne `wc -c <'im_lm.asm'`; then
  312.     echo shar: \"'im_lm.asm'\" unpacked with wrong size!
  313. fi
  314. # end of 'im_lm.asm'
  315. fi
  316. if test -f 'implode.c' -a "${1}" != "-c" ; then 
  317.   echo shar: Will not clobber existing file \"'implode.c'\"
  318. else
  319. echo shar: Extracting \"'implode.c'\" \(8838 characters\)
  320. sed "s/^X//" >'implode.c' <<'END_OF_FILE'
  321. X/*
  322. X
  323. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  324. X Permission is granted to any individual or institution to use, copy, or
  325. X redistribute this software so long as all of the original files are included
  326. X unmodified, that it is not sold for profit, and that this copyright notice
  327. X is retained.
  328. X
  329. X*/
  330. X
  331. X/*
  332. X *  implode.c by Richard B. Wales.
  333. X *
  334. X *  PURPOSE
  335. X *
  336. X *      Compress an input file using the ZIP "implosion" method.
  337. X *
  338. X *  DISCUSSION
  339. X *
  340. X *      The "implosion" algorithm is a composite of (1) OPM/L compres-
  341. X *      sion within a sliding window, and (2) variable-length binary
  342. X *      encoding of various parts of the OPM/L output.
  343. X *
  344. X *      For a detailed treatment of OPM/L compression, see the source
  345. X *      file "im_lmat.c".
  346. X *
  347. X *      For a detailed treatment of variable-length binary encoding,
  348. X *      see the source file "im_ctree.c".
  349. X *
  350. X *      Since Pass Two (binary encoding) depends on a statistical anal-
  351. X *      ysis of the entire output of Pass One (OPM/L compression), the
  352. X *      Pass One output is saved in a temporary file and re-read for
  353. X *      Pass Two.  Implosion is thus a two-pass algorithm.
  354. X *
  355. X *      An outline of the algorithm follows:
  356. X *
  357. X *      (1) The entire input file is read and compressed via the OPM/L
  358. X *          technique.  The OPM/L output is saved in a temporary file.
  359. X *
  360. X *      (2) The compressed info from (1) is analyzed, and various fre-
  361. X *          quency counts are tallied.
  362. X *
  363. X *      (3) Based on the frequency counts, a decision is made as to
  364. X *          whether or not the "literal" characters (those not matched
  365. X *          in earlier parts of the input) should be represented via a
  366. X *          binary code tree or left "as is".  If there are not very
  367. X *          many literal characters, or if their frequency distribution
  368. X *          is fairly even, the number of bits saved through coding may
  369. X *          be exceeded by the amount of info which must be included to
  370. X *          describe the tree.
  371. X *
  372. X *      (4) The temporary file from (1) is re-read.  The information is
  373. X *          further compressed via the binary code trees, and the result
  374. X *          is sent to the ZIP output file.
  375. X *
  376. X *  REFERENCES
  377. X *
  378. X *      APPNOTE.TXT documentation file in PKZIP 1.10 distribution.
  379. X *
  380. X *      See also references in the "im_lmat.c" and "im_ctree.c" source
  381. X *      files.
  382. X *
  383. X *  INTERFACE
  384. X *
  385. X *      int imp_setup (long filesize, int pack_level)
  386. X *          Initialize the "implode" routines for a new file.
  387. X *
  388. X *      int imp_p1 (char *buf, int count)
  389. X *          Process "count" input characters pointed to by "buf".  This
  390. X *          routine is called as many times as needed to process the
  391. X *          entire input file.  There is no upper limit on "count".
  392. X *
  393. X *      int imp_size (long *size, char *opts)
  394. X *          Terminate processing of the input file, and return the com-
  395. X *          pressed size ("size") and implosion option flags ("opts").
  396. X *
  397. X *      int imp_p2 (FILE *outfp)
  398. X *          Output the entire compressed file -- including S-F trees and
  399. X *          data -- to the ZIP output file "outfp".
  400. X *
  401. X *      int imp_clear (void)
  402. X *          Clean up after processing and outputting a file.  This rou-
  403. X *          tine may be called at any time to abort further processing.
  404. X *
  405. X *      All the above routines return zero if successful, or a non-zero
  406. X *      value if there was an error.
  407. X */
  408. X
  409. X#include "implode.h"
  410. X#include "ziperr.h"
  411. X
  412. X
  413. X/***********************************************************************
  414. X *
  415. X * Error return codes for the main ZIP program.
  416. X * Most of these are in "ziperr.h".
  417. X */
  418. X
  419. X#define ZE_MAP(err) \
  420. X        ( ((err) == IM_OK)      ? ZE_OK \
  421. X        : ((err) == IM_NOMEM)   ? ZE_MEM \
  422. X        : ((err) == IM_IOERR)   ? ZE_TEMP \
  423. X                                : (fprintf(stderr,"\nZE_MAP(%d)",(err)), \
  424. X                                    ZE_LOGIC))
  425. X
  426. X
  427. X/***********************************************************************
  428. X *
  429. X * State variable for the implosion routines.
  430. X */
  431. X
  432. X#define IMP_SETUP       0       /* need to do "imp_setup" */
  433. X#define IMP_P1          1       /* setup done, ready for Pass 1 */
  434. X#define IMP_P2          2       /* Pass 1 done, ready for Pass 2 */
  435. X#define IMP_CLEAR       3       /* Pass 2 done, ready for "imp_clear" */
  436. X
  437. local int imp_state = IMP_SETUP;
  438. X
  439. X
  440. X/***********************************************************************
  441. X *
  442. X * Global variables.
  443. X */
  444. X
  445. XFDATA fd;
  446. X
  447. X
  448. X/***********************************************************************
  449. X *
  450. X * Set up for performing implosion on a new file.
  451. X */
  452. X
  453. int
  454. imp_setup (filesize, pack_level)
  455. X    long filesize;  /* input file size */
  456. X    int pack_level; /* 0 = best speed, 9 = best compression, other = default */
  457. X{
  458. X    ImpErr retcode;
  459. X    extern char *tempname();
  460. X
  461. X    if (imp_state != IMP_SETUP)
  462. X    {   fprintf (stderr, "\nimp_setup called with wrong state %d",
  463. X                 imp_state);
  464. X        return ZE_LOGIC;
  465. X    }
  466. X    imp_state = IMP_P1;
  467. X
  468. X    /* Set up the initial parameters. Use an 8K window if the input
  469. X     * file is greater than or equal to 5.5K, a 4K window otherwise.
  470. X     */
  471. X    fd.fd_bufsize = 8192;
  472. X    if (filesize < 5632) fd.fd_bufsize = 4096;
  473. X
  474. X    fd.fd_strsize = 320;
  475. X    fd.fd_nbits   = (fd.fd_bufsize == 4096) ? 6 : 7;
  476. X
  477. X    /* Create a temporary file for the Pass One output. */
  478. X    fd.fd_temp = topen ('I');
  479. X    if (fd.fd_temp == NULL)
  480. X        return ZE_MEM;
  481. X
  482. X    /*
  483. X     * Initialize the "longest match" routines.
  484. X     * "ct_init" is called at this point because the "lm_input" routine
  485. X     * (called in "imp_p1") calls the "ct_tally" routine.
  486. X     */
  487. X    retcode = lm_init (pack_level);
  488. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  489. X    retcode = ct_init ();
  490. X    return ZE_MAP (retcode);
  491. X}
  492. X
  493. X
  494. X/***********************************************************************
  495. X *
  496. X * Feed characters to the implosion computation.
  497. X * This routine is called as many times as needed, until the entire
  498. X * input file has been processed.
  499. X */
  500. X
  501. int
  502. imp_p1 (buf, count)
  503. X    char *buf;                  /* input characters */
  504. X    int   count;                /* character count */
  505. X{   ImpErr retcode;
  506. X
  507. X    if (imp_state != IMP_P1)
  508. X    {   fprintf (stderr, "\nimp_p1 called with wrong state %d",
  509. X                 imp_state);
  510. X        return ZE_LOGIC;
  511. X    }
  512. X
  513. X    if (buf == NULL || count < 0)
  514. X    {   fprintf (stderr, "\nimp_p1 called with bad arguments");
  515. X        return ZE_LOGIC;
  516. X    }
  517. X    retcode = lm_input ((U_CHAR *) buf, (U_INT) count);
  518. X    return ZE_MAP (retcode);
  519. X}
  520. X
  521. X
  522. X/***********************************************************************
  523. X *
  524. X * Terminate processing of input for this file, and determine the size
  525. X * this file will have if it is imploded.  Also, find out whether two
  526. X * or three S-F trees will be used (needed for directory entries).
  527. X */
  528. X
  529. int
  530. imp_size (size, opts)
  531. X    long *size;                 /* imploded size */
  532. X    char *opts;                 /* implosion option info */
  533. X{   ImpErr retcode;
  534. X
  535. X    if (imp_state != IMP_P1)
  536. X    {   fprintf (stderr, "\nimp_size called with wrong state %d",
  537. X                 imp_state);
  538. X        return ZE_LOGIC;
  539. X    }
  540. X    imp_state = IMP_P2;
  541. X
  542. X    if (size == NULL || opts == NULL)
  543. X    {   fprintf (stderr, "\nimp_size called with bad arguments");
  544. X        return ZE_LOGIC;
  545. X    }
  546. X    retcode = lm_windup ();
  547. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  548. X    retcode = ct_mktrees ();
  549. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  550. X    *size = fd.fd_clen;
  551. X    *opts = (char)(((fd.fd_bufsize == 8192) ? 0x02 : 0)
  552. X          | ((fd.fd_method == LITERAL_TREE) ? 0x04 : 0));
  553. X    return ZE_OK;
  554. X}
  555. X
  556. X
  557. X/***********************************************************************
  558. X *
  559. X * Output the imploded version of the file (but not the file directory
  560. X * info) to the ZIP file.
  561. X */
  562. X
  563. int
  564. imp_p2 (outfp)
  565. X    FILE *outfp;                        /* output (ZIP) file */
  566. X{   ImpErr retcode;
  567. X
  568. X    if (imp_state != IMP_P2)
  569. X    {   fprintf (stderr, "\nimp_p2 called with wrong state %d",
  570. X                 imp_state);
  571. X        return ZE_LOGIC;
  572. X    }
  573. X    imp_state = IMP_CLEAR;
  574. X
  575. X    if (outfp == NULL)
  576. X    {   fprintf (stderr, "\nimp_p2 called with bad arguments");
  577. X        return ZE_LOGIC;
  578. X    }
  579. X    retcode = ct_wrtrees (outfp);
  580. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  581. X    retcode = ct_wrdata (outfp);
  582. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  583. X    fflush (outfp);
  584. X    if (ferror (outfp)) return ZE_TEMP;
  585. X    return ZE_OK;
  586. X}
  587. X
  588. X
  589. X/***********************************************************************
  590. X *
  591. X * Clean up after doing an implosion.
  592. X * This routine may also be called at any time to abort an implosion.
  593. X */
  594. X
  595. int
  596. imp_clear ()
  597. X{   (void) lm_windup ();
  598. X    if (fd.fd_temp != NULL)
  599. X        (void) tclose (fd.fd_temp);
  600. X    (void) ct_windup ();
  601. X    imp_state = IMP_SETUP;
  602. X    return ZE_OK;
  603. X}
  604. X
  605. X
  606. X/**********************************************************************/
  607. END_OF_FILE
  608. if test 8838 -ne `wc -c <'implode.c'`; then
  609.     echo shar: \"'implode.c'\" unpacked with wrong size!
  610. fi
  611. # end of 'implode.c'
  612. fi
  613. if test -f 'shrink.c' -a "${1}" != "-c" ; then 
  614.   echo shar: Will not clobber existing file \"'shrink.c'\"
  615. else
  616. echo shar: Extracting \"'shrink.c'\" \(10431 characters\)
  617. sed "s/^X//" >'shrink.c' <<'END_OF_FILE'
  618. X/*
  619. X
  620. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  621. X Permission is granted to any individual or institution to use, copy, or
  622. X redistribute this software so long as all of the original files are included
  623. X unmodified, that it is not sold for profit, and that this copyright notice
  624. X is retained.
  625. X
  626. X*/
  627. X
  628. X/*
  629. X *  shrink.c by Mark Adler.
  630. X */
  631. X
  632. X#include "zip.h"
  633. X#include "tempf.h"
  634. X
  635. X
  636. X/*
  637. X   Shrink.Pas version 1.2 by R. P. Byrne, 1989 (in Pascal and assembler).
  638. X   We here heartily acknowledge R. P. Byrne's contribution to this project.
  639. X   The existence of this program really triggered our efforts to write a
  640. X   portable Unix zip.  What little remains of Byrne's program lies in this
  641. X   source file, and those remnants are mostly in the variable and routine
  642. X   names, since it has been translated and extensively modified and rewritten.
  643. X
  644. X   Stolen, translated into C, and modified by Mark Adler, 11 October 1990.
  645. X   Severely modified again by Mark Adler, 11 July 1991, to remove the
  646. X   unnecessary FreeList and ClearTable arrays, and to replace the recursive
  647. X   Prune() routine with a non-recursive method.
  648. X   As Stravinsky once said: "Mediocre composers plagiarize.
  649. X                             Great composers steal."
  650. X*/
  651. X
  652. X/*   Compress a set of input files into a Zip file using Lempel-Ziv-Welch */
  653. X/*   (LZW) compression techniques (the "shrink" method). */
  654. X
  655. X
  656. X#define MINBITS         9       /* Starting code size of 9 bits */
  657. X#define MAXBITS         13      /* Maximum code size of 13 bits */
  658. X#define TABLESIZE       8191    /* We'll need 4K entries in table */
  659. X#define SPECIAL         256     /* Special function code */
  660. X#define INCSIZE         1       /* Code for a jump in code size */
  661. X#define CLEARCODE       2       /* Code for code table has been cleared */
  662. X#define FIRSTENTRY      257     /* First available table entry */
  663. X
  664. X
  665. X/* Define data types needed to implement a code table for LZW compression */
  666. X
  667. typedef struct CodeRec {
  668. X  /* Code Table record format... */
  669. X  short Child;          /* Addr of 1st suffix for this prefix */
  670. X  short Sibling;        /* Addr of next suffix in chain */
  671. X  uch Suffix;           /* Suffix character */
  672. X} CodeRec;
  673. X
  674. typedef CodeRec CodeArray[TABLESIZE + 1];       /* Define the code table */
  675. X
  676. X
  677. X
  678. X/* Private globals */
  679. local CodeRec far *CodeTable;   /* Points to code table for LZW compression */
  680. X
  681. local int NextFree;     /* Next free table entry */
  682. X
  683. local int CodeSize;     /* Size of codes (in bits) currently being written */
  684. local int MaxCode;      /* Largest code that can be written in CodeSize bits */
  685. X
  686. local int FirstCh;      /* Flag indicating the START of a shrink operation */
  687. X
  688. local tFILE *tempf = NULL;      /* Temporary file */
  689. local ulg count;                /* Count of bytes written */
  690. X
  691. X
  692. X/* Local functions */
  693. X#ifdef PROTO
  694. X   local void PutCode(int);
  695. X   local int Build_Data_Structures(void);
  696. X   local void Destroy_Data_Structures(void);
  697. X   local void Initialize_Data_Structures(void);
  698. X   local void Clear_Table(void);
  699. X   local void Table_Add(int, int);
  700. X#endif /* PROTO */
  701. X
  702. X
  703. X/* Macro for PutCode() that writes to tempf and counts bytes in count */
  704. X#define PUT(c) {tputc(c, tempf); count++;}
  705. X
  706. local void PutCode(c)
  707. int c;                  /* code to send */
  708. X/* Write out the low CodeSize bits of c using the PUT macro.  If c is -1,
  709. X   then flush the bit buffer.  Assumes CodeSize < 16.  By Mark Adler. */
  710. X{
  711. X  static int b = 0;     /* current bits waiting to go out */
  712. X  static int n = 0;     /* number of bits in b */
  713. X  /* masks for all bit values */
  714. X  static int x[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff,
  715. X                0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
  716. X
  717. X  if (c == -1)
  718. X  {
  719. X    if (n)
  720. X    {
  721. X      if (n > 8)
  722. X      {
  723. X        PUT((char)b)
  724. X        PUT((char)((b >> 8) & x[n - 8]))
  725. X      }
  726. X      else
  727. X        PUT((char)(b & x[n]))
  728. X      b = n = 0;
  729. X    }
  730. X  }
  731. X  else
  732. X  {
  733. X    b |= (c & x[CodeSize]) << n;
  734. X    n += CodeSize;
  735. X    if (n >= 16)
  736. X    {
  737. X      PUT((char)b)
  738. X      PUT((char)(b >> 8))
  739. X      if (n == 16)
  740. X        b = n = 0;
  741. X      else
  742. X      {
  743. X        n -= 16;
  744. X        b = (c >> (CodeSize - n)) & x[n];
  745. X      }
  746. X    }
  747. X  }
  748. X}
  749. X
  750. X
  751. X
  752. local int Build_Data_Structures()
  753. X/* Allocate tables for shrinking.  Return true on failure. */
  754. X{
  755. X  return (CodeTable = (CodeRec far *)farmalloc(sizeof(CodeArray))) == NULL;
  756. X}
  757. X
  758. X
  759. X
  760. local void Destroy_Data_Structures()
  761. X/* Deallocate tables for shrinking. */
  762. X{
  763. X  if (CodeTable != NULL)
  764. X  {
  765. X    farfree((voidp far *)CodeTable);
  766. X    CodeTable = NULL;
  767. X  }
  768. X}
  769. X
  770. X
  771. X
  772. local void Initialize_Data_Structures()
  773. X/* Clear tables for shrinking. */
  774. X{
  775. X  int i;                /* counter for table entries */
  776. X  CodeRec far *t;       /* pointer to current table entry */
  777. X
  778. X  /* Initialize parent symbols */
  779. X  for (i = 0, t = CodeTable; i <= 255; i++, t++)
  780. X  {
  781. X    t->Child = -1;
  782. X    t->Suffix = (uch)i;
  783. X  }
  784. X
  785. X  /* Build free list */
  786. X  NextFree = FIRSTENTRY;
  787. X  for (i = FIRSTENTRY, t = CodeTable + FIRSTENTRY; i < TABLESIZE; i++, t++)
  788. X    t->Child = i + 1;
  789. X  t->Child = -1;
  790. X}
  791. X
  792. X
  793. X
  794. local void Clear_Table()
  795. X/* Clear the leaves of the tree--assume all entries used (NextFree == -1) */
  796. X{
  797. X  int n;                /* node counter */
  798. X  CodeRec far *p;       /* pointer to next node to look at */
  799. X  short far *q;         /* pointer to node child or sibling entry */
  800. X
  801. X  /* Mark leaf nodes */
  802. X  p = CodeTable + TABLESIZE;
  803. X  n = TABLESIZE + 1 - FIRSTENTRY;
  804. X  do {
  805. X    if (p->Child == -1)
  806. X      p->Child = -2;
  807. X    p--;
  808. X  } while (--n);
  809. X
  810. X  /* Shake leaves from tree */
  811. X  p = CodeTable;
  812. X  n = 256;
  813. X  do {
  814. X    q = &p->Child;
  815. X    while (*q != -1 && CodeTable[*q].Child == -2)
  816. X      *q = CodeTable[*q].Sibling;
  817. X    p++;
  818. X  } while (--n);
  819. X  p = CodeTable + FIRSTENTRY;
  820. X  n = TABLESIZE + 1 - FIRSTENTRY;
  821. X  do {
  822. X    if (p->Child != -2)
  823. X    {
  824. X      q = &p->Child;
  825. X      while (*q != -1 && CodeTable[*q].Child == -2)
  826. X        *q = CodeTable[*q].Sibling;
  827. X      q = &p->Sibling;
  828. X      while (*q != -1 && CodeTable[*q].Child == -2)
  829. X        *q = CodeTable[*q].Sibling;
  830. X    }
  831. X    p++;
  832. X  } while (--n);
  833. X
  834. X  /* Build the list of free table entries */
  835. X  NextFree = -1;
  836. X  p = CodeTable + TABLESIZE;
  837. X  n = TABLESIZE + 1 - FIRSTENTRY;
  838. X  do {
  839. X    if (p->Child == -2)
  840. X    {
  841. X      p->Child = NextFree;
  842. X      NextFree = n + FIRSTENTRY - 1;
  843. X    }
  844. X    p--;
  845. X  } while (--n);
  846. X}
  847. X
  848. X
  849. X
  850. local void Table_Add(p, s)
  851. int p;                  /* prefix to add to */
  852. int s;                  /* suffix to add to it */
  853. X/* Add an entry to the table. */
  854. X{
  855. X  int f;                /* next free node */
  856. X
  857. X  if ((f = NextFree) != -1)
  858. X  {
  859. X    NextFree = CodeTable[f].Child;
  860. X    CodeTable[f].Child = -1;
  861. X    CodeTable[f].Sibling = -1;
  862. X    CodeTable[f].Suffix = (uch)s;
  863. X    if (CodeTable[p].Child == -1)
  864. X      CodeTable[p].Child = f;
  865. X    else
  866. X    {
  867. X      p = CodeTable[p].Child;
  868. X      while (CodeTable[p].Sibling != -1)
  869. X        p = CodeTable[p].Sibling;
  870. X      CodeTable[p].Sibling = f;
  871. X    }
  872. X  }
  873. X}
  874. X
  875. X
  876. local int lastcode;
  877. X
  878. int shr_setup()
  879. X/* Initialize shrink() routines.  Return an error code in the ZE_ class. */
  880. X{
  881. X  if (Build_Data_Structures())
  882. X    return ZE_MEM;
  883. X  Initialize_Data_Structures();
  884. X  FirstCh = 1;
  885. X  lastcode = -1;
  886. X  if ((tempf = topen('S')) == NULL)
  887. X    return ZE_MEM;
  888. X  count = 0;
  889. X  return ZE_OK;
  890. X}
  891. X
  892. X
  893. int shr_p1(b, n)
  894. uch *b;                 /* buffer with bytes to shrink */
  895. extent n;               /* number of bytes in buffer */
  896. X/* Shrink n bytes at *b.  Return an error code in the ZE_ class. */
  897. X{
  898. X  int f;                /* result of Table_Lookup */
  899. X  int s;                /* byte to shrink */
  900. X
  901. X  if (FirstCh && n)
  902. X  {                             /* If just getting started ... */
  903. X    CodeSize = MINBITS;         /*   Initialize code size to minimum */
  904. X    MaxCode = (1 << CodeSize) - 1;
  905. X    lastcode = *b++;  n--;      /*   get first character from input, */
  906. X    FirstCh = 0;                /*   and reset the first char flag. */
  907. X  }
  908. X  while (NextFree == -1 && n)
  909. X  {
  910. X    /* Ok, lets clear the code table (adaptive reset) */
  911. X    PutCode(lastcode);
  912. X    PutCode(SPECIAL);
  913. X    PutCode(CLEARCODE);
  914. X    Clear_Table();
  915. X    Table_Add(lastcode, s = *b++);  n--;
  916. X    lastcode = s;
  917. X  }
  918. X  while (n)
  919. X  {
  920. X    s = *b++;  n--;
  921. X    f = CodeTable[lastcode].Child;
  922. X    while (f != -1 && CodeTable[f].Suffix != (uch)s)
  923. X      f = CodeTable[f].Sibling;
  924. X    if (f != -1)
  925. X      /* If lastcode:s pair is found in the code table, then ... */
  926. X      /* ... set lastcode to the entry where the pair is located */
  927. X      lastcode = f;
  928. X    else
  929. X    {
  930. X      /* Not in table */
  931. X      PutCode(lastcode);        /* Write current lastcode */
  932. X      Table_Add(lastcode, s);   /* Attempt to add to code table */
  933. X      lastcode = s;             /* Reset lastcode for new char */
  934. X      if (NextFree > MaxCode && CodeSize < MAXBITS)
  935. X      {
  936. X        /* Time to increase the code size and change the max. code */
  937. X        PutCode(SPECIAL);
  938. X        PutCode(INCSIZE);
  939. X        CodeSize++;
  940. X        MaxCode = (1 << CodeSize) - 1;
  941. X      }
  942. X      while (NextFree == -1 && n)
  943. X      {
  944. X        /* Ok, lets clear the code table (adaptive reset) */
  945. X        PutCode(lastcode);
  946. X        PutCode(SPECIAL);
  947. X        PutCode(CLEARCODE);
  948. X        Clear_Table();
  949. X        Table_Add(lastcode, s = *b++);  n--;
  950. X        lastcode = s;
  951. X      }
  952. X    }
  953. X  }
  954. X  return ZE_OK;
  955. X}
  956. X
  957. X
  958. int shr_size(s)
  959. ulg *s;                 /* return value: size of shrunk data */
  960. X/* End shrink and return size of shrunk data in *s.  Return an error code in
  961. X   the ZE_ class. */
  962. X{
  963. X  PutCode(lastcode);            /* Write last prefix code */
  964. X  PutCode(-1);                  /* Tell putcode to flush remaining bits */
  965. X  Destroy_Data_Structures();
  966. X  *s = count;
  967. X  return tflush(tempf) || terror(tempf) ? ZE_TEMP : ZE_OK;
  968. X}
  969. X
  970. X
  971. int shr_p2(f)
  972. XFILE *f;                /* file to write shrunk data to */
  973. X/* Copy shrunk data from temporary file to zip file *f.  Return an error
  974. X   code in the ZE_ class. */
  975. X{
  976. X  char *b;              /* malloc'ed buffer for copying */
  977. X  extent k;             /* holds result of fread */
  978. X
  979. X  if ((b = malloc(BSZ)) == NULL)
  980. X    return ZE_MEM;
  981. X  trewind(tempf);
  982. X  while ((k = tread(b, 1, BSZ, tempf)) > 0)
  983. X    if (zfwrite(b, 1, k, f) != k)
  984. X    {
  985. X      free((voidp *)b);
  986. X      return ZE_TEMP;
  987. X    }
  988. X  free((voidp *)b);
  989. X  if (terror(tempf))
  990. X    return ZE_TEMP;
  991. X  tclose(tempf);
  992. X  tempf = NULL;
  993. X  return ZE_OK;
  994. X}
  995. X
  996. X
  997. int shr_clear()
  998. X/* Terminate shrink procedure (at any time).  Return an error code in
  999. X   the ZE_ class (always ZE_OK). */
  1000. X{
  1001. X  Destroy_Data_Structures();
  1002. X  if (tempf != NULL)
  1003. X  {
  1004. X    tclose(tempf);
  1005. X    tempf =  NULL;
  1006. X  }
  1007. X  return ZE_OK;
  1008. X}
  1009. END_OF_FILE
  1010. if test 10431 -ne `wc -c <'shrink.c'`; then
  1011.     echo shar: \"'shrink.c'\" unpacked with wrong size!
  1012. fi
  1013. # end of 'shrink.c'
  1014. fi
  1015. if test -f 'util.c' -a "${1}" != "-c" ; then 
  1016.   echo shar: Will not clobber existing file \"'util.c'\"
  1017. else
  1018. echo shar: Extracting \"'util.c'\" \(10800 characters\)
  1019. sed "s/^X//" >'util.c' <<'END_OF_FILE'
  1020. X/*
  1021. X
  1022. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1023. X Permission is granted to any individual or institution to use, copy, or
  1024. X redistribute this software so long as all of the original files are included
  1025. X unmodified, that it is not sold for profit, and that this copyright notice
  1026. X is retained.
  1027. X
  1028. X*/
  1029. X
  1030. X/*
  1031. X *  util.c by Mark Adler.
  1032. X */
  1033. X
  1034. X#include "zip.h"
  1035. X
  1036. X/* Local functions */
  1037. X#ifdef PROTO
  1038. X  local int recmatch(char *, char *);
  1039. X#endif /* PROTO */
  1040. X
  1041. X
  1042. char *isshexp(p)
  1043. char *p;                /* candidate sh expression */
  1044. X/* If p is a sh expression, a pointer to the first special character is
  1045. X   returned.  Otherwise, NULL is returned. */
  1046. X{
  1047. X  int c;
  1048. X
  1049. X  c = -1;
  1050. X  for (; *p; p++)
  1051. X#ifdef VMS
  1052. X    if (c != '\\' && (*p == '%' || *p == '*'))
  1053. X#else /* !VMS */
  1054. X    if (c != '\\' && (*p == '?' || *p == '*' || *p == '['))
  1055. X#endif /* ?VMS */
  1056. X      return p;
  1057. X  return NULL;
  1058. X}
  1059. X
  1060. X
  1061. local int recmatch(p, s)
  1062. char *p;                /* sh pattern to match */
  1063. char *s;                /* string to match it to */
  1064. X/* Recursively compare the sh pattern p with the string s and return 1 if
  1065. X   they match, and 0 or 2 if they don't or if there is a syntax error in the
  1066. X   pattern.  This routine recurses on itself no deeper than the number of
  1067. X   characters in the pattern. */
  1068. X{
  1069. X  int c;                /* pattern char or start of range in [-] loop */ 
  1070. X
  1071. X  /* Get first character, the pattern for new recmatch calls follows */
  1072. X  c = *p++;
  1073. X
  1074. X  /* If that was the end of the pattern, match if string empty too */
  1075. X  if (c == 0)
  1076. X    return *s == 0;
  1077. X
  1078. X  /* '?' (or '%') matches any character (but not an empty string) */
  1079. X#ifdef VMS
  1080. X  if (c == '%')
  1081. X#else /* !VMS */
  1082. X  if (c == '?')
  1083. X#endif /* ?VMS */
  1084. X    return *s ? recmatch(p, s + 1) : 0;
  1085. X
  1086. X  /* '*' matches any number of characters, including zero */
  1087. X  if (c == '*')
  1088. X  {
  1089. X    if (*p == 0)
  1090. X      return 1;
  1091. X    for (; *s; s++)
  1092. X      if ((c = recmatch(p, s)) != 0)
  1093. X        return c;
  1094. X    return 2;           /* 2 means give up--shmatch will return false */
  1095. X  }
  1096. X
  1097. X#ifndef VMS             /* No bracket matching in VMS */
  1098. X  /* Parse and process the list of characters and ranges in brackets */
  1099. X  if (c == '[')
  1100. X  {
  1101. X    int e;              /* flag true if next char to be taken literally */
  1102. X    char *q;            /* pointer to end of [-] group */
  1103. X    int r;              /* flag true to match anything but the range */
  1104. X
  1105. X    if (*s == 0)                        /* need a character to match */
  1106. X      return 0;
  1107. X    p += (r = *p == '!');               /* see if reverse */
  1108. X    for (q = p, e = 0; *q; q++)         /* find closing bracket */
  1109. X      if (e)
  1110. X        e = 0;
  1111. X      else
  1112. X        if (*q == '\\')
  1113. X          e = 1;
  1114. X        else if (*q == ']')
  1115. X          break;
  1116. X    if (*q != ']')                      /* nothing matches if bad syntax */
  1117. X      return 0;
  1118. X    for (c = 0, e = *p == '-'; p < q; p++)      /* go through the list */
  1119. X    {
  1120. X      if (e == 0 && *p == '\\')         /* set escape flag if \ */
  1121. X        e = 1;
  1122. X      else if (e == 0 && *p == '-')     /* set start of range if - */
  1123. X        c = *(p-1);
  1124. X      else
  1125. X      {
  1126. X        if (*(p+1) != '-')
  1127. X          for (c = c ? c : *p; c <= *p; c++)    /* compare range */
  1128. X#ifdef OS2
  1129. X            if (tolower(c) == tolower(*s))
  1130. X#else /* !OS2 */
  1131. X            if (c == *s)
  1132. X#endif /* ?OS2 */
  1133. X              return r ? 0 : recmatch(q + 1, s + 1);
  1134. X        c = e = 0;                      /* clear range, escape flags */
  1135. X      }
  1136. X    }
  1137. X    return r ? recmatch(q + 1, s + 1) : 0;      /* bracket match failed */
  1138. X  }
  1139. X#endif /* !VMS */
  1140. X
  1141. X  /* If escape ('\'), just compare next character */
  1142. X  if (c == '\\')
  1143. X    if ((c = *p++) == 0)                /* if \ at end, then syntax error */
  1144. X      return 0;
  1145. X
  1146. X  /* Just a character--compare it */
  1147. X#ifdef OS2
  1148. X  return tolower(c) == tolower(*s) ? recmatch(p, ++s) : 0;
  1149. X#else /* !OS2 */
  1150. X  return c == *s++ ? recmatch(p, s) : 0;        /* compare one character */
  1151. X#endif /* ?OS2 */
  1152. X}
  1153. X
  1154. X
  1155. int shmatch(p, s)
  1156. char *p;                /* sh pattern to match */
  1157. char *s;                /* string to match it to */
  1158. X/* Compare the sh pattern p with the string s and return true if they match,
  1159. X   false if they don't or if there is a syntax error in the pattern. */
  1160. X{
  1161. X  return recmatch(p, s) == 1;
  1162. X}
  1163. X
  1164. X
  1165. X#ifdef MSDOS
  1166. X
  1167. int dosmatch(p, s)
  1168. char *p;                /* dos pattern to match */
  1169. char *s;                /* string to match it to */
  1170. X/* Break the pattern and string into name and extension parts and match
  1171. X   each separately using shmatch(). */
  1172. X{
  1173. X  char *p1, *p2;        /* pattern sections */
  1174. X  char *s1, *s2;        /* string sections */
  1175. X  int r;                /* result */
  1176. X
  1177. X  if ((p1 = malloc(strlen(p) + 1)) == NULL ||
  1178. X      (s1 = malloc(strlen(s) + 1)) == NULL)
  1179. X  {
  1180. X    if (p1 != NULL)
  1181. X      free((voidp *)p1);
  1182. X    return 0;
  1183. X  }
  1184. X  strcpy(p1, p);
  1185. X  strcpy(s1, s);
  1186. X  if ((p2 = strrchr(p1, '.')) != NULL)
  1187. X    *p2++ = 0;
  1188. X  else
  1189. X    p2 = "";
  1190. X  if ((s2 = strrchr(s1, '.')) != NULL)
  1191. X    *s2++ = 0;
  1192. X  else
  1193. X    s2 = "";
  1194. X  r = shmatch(p2, s2) && shmatch(p1, s1);
  1195. X  free((voidp *)p1);
  1196. X  free((voidp *)s1);
  1197. X  return r;
  1198. X}
  1199. X
  1200. X#endif /* MSDOS */
  1201. X
  1202. X
  1203. voidp far **search(b, a, n, cmp)
  1204. voidp *b;               /* pointer to value to search for */
  1205. voidp far **a;          /* table of pointers to values, sorted */
  1206. extent n;               /* number of pointers in a[] */
  1207. int (*cmp) OF((voidp *, voidp far *));  /* comparison function for search */
  1208. X/* Search for b in the pointer list a[0..n-1] using the compare function
  1209. X   cmp(b, c) where c is an element of a[i] and cmp() returns negative if
  1210. X   *b < *c, zero if *b == *c, or positive if *b > *c.  If *b is found,
  1211. X   search returns a pointer to the entry in a[], else search() returns
  1212. X   NULL.  The nature and size of *b and *c (they can be different) are
  1213. X   left up to the cmp() function.  A binary search is used, and it is
  1214. X   assumed that the list is sorted in ascending order. */
  1215. X{
  1216. X  voidp far **i;        /* pointer to midpoint of current range */
  1217. X  voidp far **l;        /* pointer to lower end of current range */
  1218. X  int r;                /* result of (*cmp)() call */
  1219. X  voidp far **u;        /* pointer to upper end of current range */
  1220. X
  1221. X  l = (voidp far **)a;  u = l + (n-1);
  1222. X  while (u >= l)
  1223. X    if ((r = (*cmp)(b, *(i = l + ((u - l) >> 1)))) < 0)
  1224. X      u = i - 1;
  1225. X    else if (r > 0)
  1226. X      l = i + 1;
  1227. X    else
  1228. X      return (voidp far **)i;
  1229. X  return NULL;          /* If b were in list, it would belong at l */
  1230. X}
  1231. X
  1232. X
  1233. X
  1234. X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
  1235. local ulg crctab[] = {
  1236. X  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  1237. X  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  1238. X  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  1239. X  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  1240. X  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  1241. X  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  1242. X  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  1243. X  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  1244. X  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  1245. X  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  1246. X  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  1247. X  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  1248. X  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  1249. X  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  1250. X  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  1251. X  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  1252. X  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  1253. X  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  1254. X  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  1255. X  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  1256. X  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  1257. X  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  1258. X  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  1259. X  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  1260. X  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  1261. X  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  1262. X  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  1263. X  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  1264. X  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  1265. X  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  1266. X  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  1267. X  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  1268. X  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  1269. X  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  1270. X  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  1271. X  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  1272. X  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  1273. X  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  1274. X  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  1275. X  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  1276. X  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  1277. X  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  1278. X  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  1279. X  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  1280. X  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  1281. X  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  1282. X  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  1283. X  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  1284. X  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  1285. X  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  1286. X  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  1287. X  0x2d02ef8dL
  1288. X};
  1289. X
  1290. X
  1291. ulg crc32(c, b)
  1292. ulg c;                  /* current contents of crc shift register */
  1293. int b;                  /* byte (eight bits) to run through */
  1294. X/* Return the CRC-32 c updated with the eight bits in b. */
  1295. X{
  1296. X  return crctab[((int)c ^ b) & 0xff] ^ (c >> 8);
  1297. X}
  1298. X
  1299. X
  1300. ulg updcrc(s, n)
  1301. char *s;                /* pointer to bytes to pump through */
  1302. extent n;               /* number of bytes in s[] */
  1303. X/* Run a set of bytes through the crc shift register.  If s is a NULL
  1304. X   pointer, then initialize the crc shift register contents instead.
  1305. X   Return the current crc in either case. */
  1306. X{
  1307. X  register ulg c;       /* temporary variable */
  1308. X
  1309. X  static ulg crc = 0xffffffffL; /* shift register contents */
  1310. X
  1311. X  if (s == NULL)
  1312. X    c = 0xffffffffL;
  1313. X  else
  1314. X  {
  1315. X    c = crc;
  1316. X    while (n--)
  1317. X      c = crctab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
  1318. X  }
  1319. X  crc = c;
  1320. X  return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
  1321. X}
  1322. END_OF_FILE
  1323. if test 10800 -ne `wc -c <'util.c'`; then
  1324.     echo shar: \"'util.c'\" unpacked with wrong size!
  1325. fi
  1326. # end of 'util.c'
  1327. fi
  1328. if test -f 'zip.h' -a "${1}" != "-c" ; then 
  1329.   echo shar: Will not clobber existing file \"'zip.h'\"
  1330. else
  1331. echo shar: Extracting \"'zip.h'\" \(8017 characters\)
  1332. sed "s/^X//" >'zip.h' <<'END_OF_FILE'
  1333. X/*
  1334. X
  1335. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1336. X Permission is granted to any individual or institution to use, copy, or
  1337. X redistribute this software so long as all of the original files are included
  1338. X unmodified, that it is not sold for profit, and that this copyright notice
  1339. X is retained.
  1340. X
  1341. X*/
  1342. X
  1343. X/*
  1344. X *  zip.h by Mark Adler.
  1345. X */
  1346. X
  1347. X
  1348. X/* Set up portability */
  1349. X#include "tailor.h"
  1350. X
  1351. X/* Define malloc() and string functions */
  1352. X#ifdef MODERN
  1353. X#  include <string.h>
  1354. X#else /* !MODERN */
  1355. X   voidp *malloc();
  1356. X   char *getenv();
  1357. X   long atol();
  1358. X   char *strcpy();
  1359. X   char *strcat();
  1360. X   char *strchr();
  1361. X   char *strrchr();
  1362. X#  ifndef ZMEM
  1363. X     char *memset();
  1364. X     char *memcpy();
  1365. X#  endif /* !ZMEM */
  1366. X#endif /* ?MODERN */
  1367. X
  1368. X
  1369. X/* Define fseek() commands */
  1370. X#ifndef SEEK_SET
  1371. X#  define SEEK_SET 0
  1372. X#endif /* !SEEK_SET */
  1373. X
  1374. X#ifndef SEEK_CUR
  1375. X#  define SEEK_CUR 1
  1376. X#endif /* !SEEK_CUR */
  1377. X
  1378. X
  1379. X/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */
  1380. X#ifdef MSDOS
  1381. X#  define FNMAX 256
  1382. X#else /* !MSDOS */
  1383. X#  define FNMAX 1024
  1384. X#endif /* ?MSDOS */
  1385. X
  1386. X
  1387. X/* Types centralized here for easy modification */
  1388. X#define local static            /* More meaningful outside functions */
  1389. typedef unsigned char uch;      /* unsigned 8-bit value */
  1390. typedef unsigned short ush;     /* unsigned 16-bit value */
  1391. typedef unsigned long ulg;      /* unsigned 32-bit value */
  1392. X
  1393. X
  1394. X/* Lengths of headers after signatures in bytes */
  1395. X#define LOCHEAD 26
  1396. X#define CENHEAD 42
  1397. X#define ENDHEAD 18
  1398. X
  1399. X
  1400. X/* Structures for in-memory file information */
  1401. struct zlist {
  1402. X  /* See central header in zipfile.c for what vem..off are */
  1403. X  ush vem, ver, flg, how;
  1404. X  ulg tim, crc, siz, len;
  1405. X  extent nam, ext, cext, com;   /* offset of ext must be >= LOCHEAD */
  1406. X  ush dsk, att, lflg;           /* offset of lflg must be >= LOCHEAD */
  1407. X  ulg atx, off;
  1408. X  char *name;                   /* File name in zip file */
  1409. X  char *extra;                  /* Extra field (set only if ext != 0) */
  1410. X  char *cextra;                 /* Extra in central (set only if cext != 0) */
  1411. X  char *comment;                /* Comment (set only if com != 0) */
  1412. X  char *zname;                  /* Name for new zip file header */
  1413. X  int mark;                     /* Marker for files to operate on */
  1414. X  int trash;                    /* Marker for files to delete */
  1415. X  struct zlist far *nxt;        /* Pointer to next header in list */
  1416. X};
  1417. struct flist {
  1418. X  char *name;                   /* Pointer to zero-delimited name */
  1419. X  char *zname;                  /* Name used for zip file headers */
  1420. X  struct flist far * far *lst;  /* Pointer to link pointing here */
  1421. X  struct flist far *nxt;        /* Link to next name */
  1422. X};
  1423. X
  1424. X
  1425. X/* Error return codes and PERR macro */
  1426. X#include "ziperr.h"
  1427. X
  1428. X
  1429. X/* Public globals */
  1430. extern char errbuf[];           /* Handy place to build error messages */
  1431. extern int recurse;             /* Recurse into directories encountered */
  1432. extern int pathput;             /* Store path with name */
  1433. X#define BEST -1                 /* Use best method */
  1434. X#define STORE 0                 /* Store method */
  1435. X#define SHRINK 1                /* Use shrink or store only */
  1436. X#define IMPLODE 6               /* Use implode or store only */
  1437. extern int method;              /* Restriction on compression method */
  1438. extern int dosify;              /* Make new entries look like MSDOS */
  1439. extern char *special;           /* Don't compress special suffixes */
  1440. extern int verbose;             /* Report oddities in zip file structure */
  1441. extern int level;               /* Compression level */
  1442. X#ifdef VMS
  1443. X   extern int vmsver;           /* Append VMS version number to file names */
  1444. X#endif /* VMS */
  1445. extern int linkput;             /* Store symbolic links as such */
  1446. extern int noisy;               /* False for quiet operation */
  1447. extern char *key;               /* Scramble password or NULL */
  1448. extern char *tempath;           /* Path for temporary files */
  1449. extern char *zipfile;           /* New or existing zip archive (zip file) */
  1450. extern ulg zipbeg;              /* Starting offset of zip structures */
  1451. extern ulg cenbeg;              /* Starting offset of central directory */
  1452. extern struct zlist far *zfiles;/* Pointer to list of files in zip file */
  1453. extern extent zcount;           /* Number of files in zip file */
  1454. extern extent zcomlen;          /* Length of zip file comment */
  1455. extern char *zcomment;          /* Zip file comment (not zero-terminated) */
  1456. extern struct zlist far **zsort;/* List of files sorted by name */
  1457. extern struct flist far *found; /* List of names found */
  1458. extern struct flist far * far *fnxt;    /* Where to put next in found list */
  1459. extern extent fcount;           /* Count of names in found list */
  1460. extern int shract;              /* Shrink active */
  1461. extern int impact;              /* Implosion active */
  1462. X
  1463. X
  1464. X/* Diagnostic function */
  1465. X#ifdef DEBUG
  1466. X#  define diag(where) fprintf(stderr, "zip diagnostic: %s\n", where)
  1467. X#else /* !DEBUG */
  1468. X#  define diag(where)
  1469. X#endif /* ?DEBUG */
  1470. X
  1471. X
  1472. X/* Public function prototypes */
  1473. X
  1474. X        /* in zip.c, zipcloak.c, or zipsplit.c */
  1475. void warn OF((char *, char *));
  1476. X
  1477. X        /* in zipup.c */
  1478. int zipcopy OF((struct zlist far *, FILE *, FILE *));
  1479. X#ifndef UTIL
  1480. X   int percent OF((ulg, ulg));
  1481. X   int zipup OF((struct zlist far *, FILE *));
  1482. X#endif /* !UTIL */
  1483. X
  1484. X        /* in zipfile.c */
  1485. X#ifndef UTIL
  1486. X   struct zlist far *zsearch OF((char *));
  1487. X   int trash OF((void));
  1488. X#endif /* !UTIL */
  1489. char *ziptyp OF((char *));
  1490. int readzipfile OF((void));
  1491. int putlocal OF((struct zlist far *, FILE *));
  1492. int putcentral OF((struct zlist far *, FILE *));
  1493. int putend OF((int, ulg, ulg, extent, char *, FILE *));
  1494. X
  1495. X        /* in fileio.c */
  1496. X#ifndef UTIL
  1497. X#  ifdef MSDOS
  1498. X     int wild OF((char *));
  1499. X#  endif /* MSDOS */
  1500. X   char *getnam OF((char *));
  1501. X   struct flist far *fexpel OF((struct flist far *));
  1502. X   char *in2ex OF((char *));
  1503. X   int exclude OF((void));
  1504. X   int procname OF((char *));
  1505. X   void stamp OF((char *, ulg));
  1506. X   ulg dostime OF((int, int, int, int, int, int));
  1507. X   ulg filetime OF((char *, ulg *, long *));
  1508. X   int issymlnk OF((ulg a));
  1509. X#  ifdef S_IFLNK
  1510. X#    define rdsymlnk(p,b,n) readlink(p,b,n)
  1511. X     extern int readlink OF((char *, char *, int));
  1512. X#  else /* !S_IFLNK */
  1513. X#    define rdsymlnk(p,b,n) (0)
  1514. X#  endif /* !S_IFLNK */
  1515. X   int deletedir OF((char *));
  1516. X#endif /* !UTIL */
  1517. int destroy OF((char *));
  1518. int replace OF((char *, char *));
  1519. int getfileattr OF((char *));
  1520. int setfileattr OF((char *, int));
  1521. char *tempname OF((int));
  1522. int fcopy OF((FILE *, FILE *, ulg));
  1523. X#ifndef EXPORT
  1524. X#  ifndef MSVMS
  1525. X     void echoff OF((int));
  1526. X     void echon OF((void));
  1527. X#  endif /* !MSVMS */
  1528. X   char *getp OF((char *, char *, int));
  1529. X#endif /* !EXPORT */
  1530. X#ifdef ZMEM
  1531. X   char *memset OF((char *, int, unsigned int));
  1532. X   char *memcpy OF((char *, char *, unsigned int));
  1533. X   int memcmp OF((char *, char *, unsigned int));
  1534. X#endif /* ZMEM */
  1535. X
  1536. X        /* in crypt.c */
  1537. X#ifdef EXPORT
  1538. X#  define zfwrite fwrite
  1539. X#else /* !EXPORT */
  1540. X   void crypthead OF((char *, ulg, FILE *));
  1541. X#  ifdef UTIL
  1542. X     int zipcloak OF ((struct zlist far *, FILE *, FILE *, char *));
  1543. X     int zipbare OF ((struct zlist far *, FILE *, FILE *, char *));
  1544. X#  else /* !UTIL */
  1545. X     int zfwrite OF((voidp *, extent, extent, FILE *));
  1546. X     int zfputc OF((int, FILE *));
  1547. X#  endif /* ?UTIL */
  1548. X#endif /* ?EXPORT */
  1549. X
  1550. X        /* in util.c */
  1551. char *isshexp OF((char *));
  1552. int shmatch OF((char *, char *));
  1553. X#ifdef MSDOS
  1554. X   int dosmatch OF((char *, char *));
  1555. X#endif /* MSDOS */
  1556. voidp far **search OF((voidp *, voidp far **, extent,
  1557. X                       int (*)(voidp *, voidp far *)));
  1558. ulg crc32 OF((ulg, int));
  1559. ulg updcrc OF((char *, extent));
  1560. X
  1561. X        /* in shrink.c */
  1562. X#ifndef UTIL
  1563. X   int shr_setup OF((void));
  1564. X   int shr_p1 OF((uch *, extent));
  1565. X   int shr_size OF((ulg *));
  1566. X   int shr_p2 OF((FILE *));
  1567. X   int shr_clear OF((void));
  1568. X  
  1569. X        /* in implode.c */
  1570. X#  ifndef NOIMPLODE
  1571. X     int imp_setup OF((long, int));
  1572. X     int imp_p1 OF((char *, int));
  1573. X     int imp_size OF((ulg *, uch *));
  1574. X     int imp_p2 OF((FILE *));
  1575. X     int imp_clear OF((void));
  1576. X#  endif /* !NOIMPLODE */
  1577. X#endif /* !UTIL */
  1578. X
  1579. X
  1580. X/* end of zip.h */
  1581. END_OF_FILE
  1582. if test 8017 -ne `wc -c <'zip.h'`; then
  1583.     echo shar: \"'zip.h'\" unpacked with wrong size!
  1584. fi
  1585. # end of 'zip.h'
  1586. fi
  1587. if test -f 'zipnote.c' -a "${1}" != "-c" ; then 
  1588.   echo shar: Will not clobber existing file \"'zipnote.c'\"
  1589. else
  1590. echo shar: Extracting \"'zipnote.c'\" \(9810 characters\)
  1591. sed "s/^X//" >'zipnote.c' <<'END_OF_FILE'
  1592. X/*
  1593. X
  1594. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1595. X Permission is granted to any individual or institution to use, copy, or
  1596. X redistribute this software so long as all of the original files are included
  1597. X unmodified, that it is not sold for profit, and that this copyright notice
  1598. X is retained.
  1599. X
  1600. X*/
  1601. X
  1602. X/*
  1603. X *  zipnote.c by Mark Adler.
  1604. X */
  1605. X
  1606. X#define UTIL
  1607. X#include "revision.h"
  1608. X#include "zip.h"
  1609. X#include <signal.h>
  1610. X
  1611. X
  1612. X/* Character to mark zip entry names in the comment file */
  1613. X#define MARK '@'
  1614. X
  1615. X/* Temporary zip file name and file pointer */
  1616. local char *tempzip;
  1617. local FILE *tempzf;
  1618. X
  1619. X
  1620. X/* Local functions */
  1621. X#ifdef PROTO
  1622. X   local void err(int, char *);
  1623. X   local void handler(int);
  1624. X   local void license(void);
  1625. X   local void help(void);
  1626. X   local void putclean(char *);
  1627. X   local int catalloc(char * far *, char *);
  1628. X   void main(int, char **);
  1629. X#endif /* PROTO */
  1630. X
  1631. X
  1632. X
  1633. local void err(c, h)
  1634. int c;                  /* error code from the ZE_ class */
  1635. char *h;                /* message about how it happened */
  1636. X/* Issue a message for the error, clean up files and memory, and exit. */
  1637. X{
  1638. X  if (PERR(c))
  1639. X    perror("zipnote error");
  1640. X  fprintf(stderr, "zipnote error: %s (%s)\n", errors[c-1], h);
  1641. X  if (tempzf != NULL)
  1642. X    fclose(tempzf);
  1643. X  if (tempzip != NULL)
  1644. X  {
  1645. X    destroy(tempzip);
  1646. X    free((voidp *)tempzip);
  1647. X  }
  1648. X  if (zipfile != NULL)
  1649. X    free((voidp *)zipfile);
  1650. X#ifdef VMS
  1651. X  exit(0);
  1652. X#else /* !VMS */
  1653. X  exit(c);
  1654. X#endif /* ?VMS */
  1655. X}
  1656. X
  1657. X
  1658. local void handler(s)
  1659. int s;                  /* signal number (ignored) */
  1660. X/* Upon getting a user interrupt, abort cleanly using err(). */
  1661. X{
  1662. X#ifndef MSDOS
  1663. X  putc('\n', stderr);
  1664. X#endif /* !MSDOS */
  1665. X  err(ZE_ABORT, "aborting");
  1666. X  s++;                                  /* keep some compilers happy */
  1667. X}
  1668. X
  1669. X
  1670. void warn(a, b)
  1671. char *a, *b;            /* message strings juxtaposed in output */
  1672. X/* Print a warning message to stderr and return. */
  1673. X{
  1674. X  fprintf(stderr, "zipnote warning: %s%s\n", a, b);
  1675. X}
  1676. X
  1677. X
  1678. local void license()
  1679. X/* Print license information to stdout. */
  1680. X{
  1681. X  extent i;             /* counter for copyright array */
  1682. X
  1683. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  1684. X    puts(copyright[i]);
  1685. X  for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
  1686. X    puts(disclaimer[i]);
  1687. X}
  1688. X
  1689. X
  1690. local void help()
  1691. X/* Print help (along with license info) to stdout. */
  1692. X{
  1693. X  extent i;             /* counter for help array */
  1694. X
  1695. X  /* help array */
  1696. X  static char *text[] = {
  1697. X"",
  1698. X"ZipNote %d.%d (%s)",
  1699. X"Usage:  zipnote [-w] [-b path] zipfile",
  1700. X"  the default action is to write the comments in zipfile to stdout",
  1701. X"  -w   write the zipfile comments from stdin",
  1702. X"  -b   use \"path\" for the temporary zip file",
  1703. X"  -h   show this help               -l   show software license",
  1704. X"",
  1705. X"Example:",
  1706. X#ifdef VMS
  1707. X"     define/user sys$output foo.tmp",
  1708. X"     zipnote foo.zip",
  1709. X"     edit foo.tmp",
  1710. X"     ... then you edit the comments, save, and exit ...",
  1711. X"     define/user sys$input foo.tmp",
  1712. X"     zipnote -w foo.zip"
  1713. X#else /* !VMS */
  1714. X"     zipnote foo.zip > foo.tmp",
  1715. X"     ed foo.tmp",
  1716. X"     ... then you edit the comments, save, and exit ...",
  1717. X"     zipnote -w foo.zip < foo.tmp"
  1718. X#endif /* ?VMS */
  1719. X  };
  1720. X
  1721. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  1722. X    puts(copyright[i]);
  1723. X  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  1724. X  {
  1725. X    printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
  1726. X    putchar('\n');
  1727. X  }
  1728. X}
  1729. X
  1730. X
  1731. local void putclean(s)
  1732. char *s;                /* string to write to stdout */
  1733. X/* Write the string s to stdout, filtering out control characters that are
  1734. X   not tab or newline (mainly to remove carriage returns), and prefix MARK's
  1735. X   and backslashes with a backslash.  Also, terminate with a newline if
  1736. X   needed. */
  1737. X{
  1738. X  int c;                /* next character in string */
  1739. X  int e;                /* last character written */
  1740. X
  1741. X  e = '\n';                     /* if empty, write nothing */
  1742. X  while ((c = *s++) != 0)
  1743. X  {
  1744. X    if (c == MARK || c == '\\')
  1745. X      putchar('\\');
  1746. X    if (c >= ' ' || c == '\t' || c == '\n')
  1747. X      putchar(e = c);
  1748. X  }
  1749. X  if (e != '\n')
  1750. X    putchar('\n');
  1751. X}
  1752. X
  1753. X
  1754. local int catalloc(a, s)
  1755. char * far *a;          /* pointer to a pointer to a malloc'ed string */
  1756. char *s;                /* string to concatenate on a */
  1757. X/* Concatentate the string s to the malloc'ed string pointed to by a.
  1758. X   Preprocess s by removing backslash escape characters. */
  1759. X{
  1760. X  char *p;              /* temporary pointer */
  1761. X  char *q;              /* temporary pointer */
  1762. X
  1763. X  for (p = q = s; *q; *p++ = *q++)
  1764. X    if (*q == '\\' && *(q+1))
  1765. X      q++;
  1766. X  *p = 0;
  1767. X  if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
  1768. X    return ZE_MEM;
  1769. X  strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
  1770. X  free((voidp *)*a);
  1771. X  *a = p;
  1772. X  return ZE_OK;
  1773. X}
  1774. X
  1775. X
  1776. void main(argc, argv)
  1777. int argc;               /* number of tokens in command line */
  1778. char **argv;            /* command line tokens */
  1779. X/* Write the comments in the zipfile to stdout, or read them from stdin. */
  1780. X{
  1781. X  char a[FNMAX+1];      /* input line buffer */
  1782. X  ulg c;                /* start of central directory */
  1783. X  int k;                /* next argument type */
  1784. X  char *q;              /* steps through option arguments */
  1785. X  int r;                /* arg counter, temporary variable */
  1786. X  ulg s;                /* length of central directory */
  1787. X  int t;                /* attributes of zip file */
  1788. X  int w;                /* true if updating zip file from stdin */
  1789. X  FILE *x, *y;          /* input and output zip files */
  1790. X  struct zlist far *z;  /* steps through zfiles linked list */
  1791. X
  1792. X
  1793. X  /* If no args, show help */
  1794. X  if (argc == 1)
  1795. X  {
  1796. X    help();
  1797. X    exit(0);
  1798. X  }
  1799. X
  1800. X  /* Go through args */
  1801. X  zipfile = tempzip = NULL;
  1802. X  tempzf = NULL;
  1803. X  signal(SIGINT, handler);
  1804. X  signal(SIGTERM, handler);
  1805. X  k = w = 0;
  1806. X  for (r = 1; r < argc; r++)
  1807. X    if (*argv[r] == '-')
  1808. X      if (argv[r][1])
  1809. X        for (q = argv[r]+1; *q; q++)
  1810. X          switch(*q)
  1811. X          {
  1812. X            case 'b':   /* Specify path for temporary file */
  1813. X              if (k)
  1814. X                err(ZE_PARMS, "use -b before zip file name");
  1815. X              else
  1816. X                k = 1;          /* Next non-option is path */
  1817. X              break;
  1818. X            case 'h':   /* Show help */
  1819. X              help();  exit(0);
  1820. X            case 'l':   /* Show copyright and disclaimer */
  1821. X              license();  exit(0);
  1822. X            case 'w':
  1823. X              w = 1;  break;
  1824. X            default:
  1825. X              err(ZE_PARMS, "unknown option");
  1826. X          }
  1827. X      else
  1828. X        err(ZE_PARMS, "zip file cannot be stdin");
  1829. X    else
  1830. X      if (k == 0)
  1831. X        if (zipfile == NULL)
  1832. X        {
  1833. X          if ((zipfile = ziptyp(argv[r])) == NULL)
  1834. X            err(ZE_MEM, "was processing arguments");
  1835. X        }
  1836. X        else
  1837. X          err(ZE_PARMS, "can only specify one zip file");
  1838. X      else
  1839. X      {
  1840. X        tempath = argv[r];
  1841. X        k = 0;
  1842. X      }
  1843. X  if (zipfile == NULL)
  1844. X    err(ZE_PARMS, "need to specify zip file");
  1845. X
  1846. X  /* Read zip file */
  1847. X  if ((r = readzipfile()) != ZE_OK)
  1848. X    err(r, zipfile);
  1849. X  if (zfiles == NULL)
  1850. X    err(ZE_NAME, zipfile);
  1851. X
  1852. X  /* Put comments to stdout, if not -u */
  1853. X  if (!w)
  1854. X  {
  1855. X    for (z = zfiles; z != NULL; z = z->nxt)
  1856. X    {
  1857. X      printf("%c %s\n", MARK, z->zname);
  1858. X      if (z->com)
  1859. X        putclean(z->comment);
  1860. X      putchar(MARK);  putchar('\n');
  1861. X    }
  1862. X    putchar(MARK);  putchar('\n');
  1863. X    if (zcomlen)
  1864. X      putclean(zcomment);
  1865. X    exit(ZE_OK);
  1866. X  }
  1867. X
  1868. X  /* If updating comments, make sure zip file is writeable */
  1869. X  if ((x = fopen(zipfile, "a")) == NULL)
  1870. X    err(ZE_CREAT, zipfile);
  1871. X  fclose(x);
  1872. X  t = getfileattr(zipfile);
  1873. X
  1874. X  /* Process stdin, replacing comments */
  1875. X  for (z = zfiles; z != NULL; z = z->nxt)
  1876. X  {
  1877. X    if (gets(a) == NULL || a[0] != MARK || a[1] != ' ' ||
  1878. X        strcmp(a + 2, z->zname))
  1879. X      err(ZE_NOTE, "missing entry name");
  1880. X    if (z->com)
  1881. X      free((voidp *)z->comment);
  1882. X    z->comment = malloc(1);  *(z->comment) = 0;
  1883. X    while (gets(a) != NULL && *a != MARK)
  1884. X      if ((r = catalloc(&(z->comment), a)) != ZE_OK)
  1885. X        err(r, "was building new comments");
  1886. X    if (a[1])
  1887. X      err(ZE_NOTE, "missing comment end line");
  1888. X    z->com = strlen(z->comment);
  1889. X  }
  1890. X  if (gets(a) == NULL || a[0] != MARK || a[1])
  1891. X    err(ZE_NOTE, "missing zip file comment marker line");
  1892. X  zcomment = malloc(1);  *zcomment = 0;
  1893. X  while (gets(a) != NULL)
  1894. X    if ((r = catalloc(&zcomment, a)) != ZE_OK)
  1895. X      err(r, "was building new comments");
  1896. X  zcomlen = strlen(zcomment);
  1897. X
  1898. X  /* Open output zip file for writing */
  1899. X  if ((tempzf = y = fopen(tempzip = tempname('Z'), FOPW)) == NULL)
  1900. X    err(ZE_TEMP, tempzip);
  1901. X
  1902. X  /* Open input zip file again, copy preamble if any */
  1903. X  if ((x = fopen(zipfile, FOPR)) == NULL)
  1904. X    err(ZE_NAME, zipfile);
  1905. X  if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
  1906. X    err(r, r == ZE_TEMP ? tempzip : zipfile);
  1907. X
  1908. X  /* Go through local entries, copying them over as is */
  1909. X  for (z = zfiles; z != NULL; z = z->nxt)
  1910. X    if ((r = zipcopy(z, x, y)) != ZE_OK)
  1911. X      err(r, "was copying an entry");
  1912. X  fclose(x);
  1913. X
  1914. X  /* Write central directory and end of central directory with new comments */
  1915. X  if ((c = ftell(y)) == -1L)    /* get start of central */
  1916. X    err(ZE_TEMP, tempzip);
  1917. X  for (z = zfiles; z != NULL; z = z->nxt)
  1918. X    if ((r = putcentral(z, y)) != ZE_OK)
  1919. X      err(r, tempzip);
  1920. X  if ((s = ftell(y)) == -1L)    /* get end of central */
  1921. X    err(ZE_TEMP, tempzip);
  1922. X  s -= c;                       /* compute length of central */
  1923. X  if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
  1924. X    err(r, tempzip);
  1925. X  tempzf = NULL;
  1926. X  if (fclose(y))
  1927. X    err(ZE_TEMP, tempzip);
  1928. X  if ((r = replace(zipfile, tempzip)) != ZE_OK)
  1929. X  {
  1930. X    warn("new zip file left as: ", tempzip);
  1931. X    free((voidp *)tempzip);
  1932. X    tempzip = NULL;
  1933. X    err(r, "was replacing the original zip file");
  1934. X  }
  1935. X  free((voidp *)tempzip);
  1936. X  tempzip = NULL;
  1937. X  setfileattr(zipfile, t);
  1938. X  free((voidp *)zipfile);
  1939. X  zipfile = NULL;
  1940. X
  1941. X  /* Done! */
  1942. X  exit(ZE_OK);
  1943. X}
  1944. END_OF_FILE
  1945. if test 9810 -ne `wc -c <'zipnote.c'`; then
  1946.     echo shar: \"'zipnote.c'\" unpacked with wrong size!
  1947. fi
  1948. # end of 'zipnote.c'
  1949. fi
  1950. if test -f 'zipup.c' -a "${1}" != "-c" ; then 
  1951.   echo shar: Will not clobber existing file \"'zipup.c'\"
  1952. else
  1953. echo shar: Extracting \"'zipup.c'\" \(10409 characters\)
  1954. sed "s/^X//" >'zipup.c' <<'END_OF_FILE'
  1955. X/*
  1956. X
  1957. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1958. X Permission is granted to any individual or institution to use, copy, or
  1959. X redistribute this software so long as all of the original files are included
  1960. X unmodified, that it is not sold for profit, and that this copyright notice
  1961. X is retained.
  1962. X
  1963. X*/
  1964. X
  1965. X/*
  1966. X *  zipup.c by Mark Adler.
  1967. X */
  1968. X
  1969. X#define NOCPYRT         /* this is not a main module */
  1970. X#include "zip.h"
  1971. X#include "revision.h"
  1972. X
  1973. X/* Use the raw functions for MSDOS and Unix to save on buffer space.
  1974. X   They're not used for VMS since it doesn't work (raw is weird on VMS).
  1975. X   (This sort of stuff belongs in fileio.c, but oh well.) */
  1976. X#ifdef VMS
  1977. X   typedef FILE *ftype;
  1978. X#  define fhow FOPR
  1979. X#  define fbad NULL
  1980. X#  define zopen(n,p) fopen(n,p)
  1981. X#  define zread(f,b,n) fread(b,1,n,f)
  1982. X#  define zclose(f) fclose(f)
  1983. X#  define zerr(f) ferror(f)
  1984. X#  define zrew(f) rewind(f)
  1985. X#else /* !VMS */
  1986. X#  ifdef MSDOS
  1987. X#    include <io.h>
  1988. X#    include <fcntl.h>
  1989. X#    define fhow (O_RDONLY|O_BINARY)
  1990. X#  else /* !MSDOS */
  1991. X     int open OF((char *, int));
  1992. X     int read OF((int, char *, int));
  1993. X     int close OF((int));
  1994. X     int lseek OF((int,long,int));
  1995. X#    define fhow 0
  1996. X#  endif /* ?MSDOS */
  1997. X   typedef int ftype;
  1998. X#  define fbad (-1)
  1999. X#  define zopen(n,p) open(n,p)
  2000. X#  define zread(f,b,n) read(f,b,n)
  2001. X#  define zclose(f) close(f)
  2002. X#  define zerr(f) (k<0)
  2003. X#  define zrew(f) lseek(f,0L,0)
  2004. X#endif /* ?VMS */
  2005. X
  2006. X
  2007. X/* Local functions */
  2008. X#ifdef PROTO
  2009. X#  ifndef UTIL
  2010. X     local int suffixes(char *, char *);
  2011. X#  endif /* !UTIL */
  2012. X#endif /* PROTO */
  2013. X
  2014. X
  2015. X/* Note: a zip "entry" includes a local header (which includes the file
  2016. X   name), an encryption header if encrypting, and the compressed data. */
  2017. X
  2018. X
  2019. int zipcopy(z, x, y)
  2020. struct zlist far *z;    /* zip entry to copy */
  2021. XFILE *x, *y;            /* source and destination files */
  2022. X/* Copy the zip entry described by *z from file *x to file *y.  Return an
  2023. X   error code in the ZE_ class.  */
  2024. X{
  2025. X  ulg n;                /* holds local header offset */
  2026. X
  2027. X  if (fseek(x, z->off, SEEK_SET))
  2028. X    return ferror(x) ? ZE_READ : ZE_EOF;
  2029. X  if ((n = ftell(y)) == -1L)
  2030. X    return ZE_TEMP;
  2031. X  z->off = n;
  2032. X  n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
  2033. X  return fcopy(x, y, n);
  2034. X}
  2035. X
  2036. X
  2037. X#ifndef UTIL
  2038. X
  2039. int percent(n, m)
  2040. ulg n, m;               /* n is the original size, m is the new size */
  2041. X/* Return the percentage compression from n to m using only integer
  2042. X   operations */
  2043. X{
  2044. X  if (n > 0xffffffL)            /* If n >= 16M */
  2045. X  {                             /*  then divide n and m by 256 */
  2046. X    n += 0x80;  n >>= 8;
  2047. X    m += 0x80;  m >>= 8;
  2048. X  }
  2049. X  return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
  2050. X}
  2051. X
  2052. X
  2053. local int suffixes(a, s)
  2054. char *a;                /* name to check suffix of */
  2055. char *s;                /* list of suffixes separated by : or ; */
  2056. X/* Return true if a ends in any of the suffixes in the list s. */
  2057. X{
  2058. X  int m;                /* true if suffix matches so far */
  2059. X  char *p;              /* pointer into special */
  2060. X  char *q;              /* pointer into name a */
  2061. X
  2062. X  m = 1;
  2063. X  q = a + strlen(a) - 1;
  2064. X  for (p = s + strlen(s) - 1; p >= s; p--)
  2065. X    if (*p == ':' || *p == ';')
  2066. X      if (m)
  2067. X        return 1;
  2068. X      else
  2069. X      {
  2070. X        m = 1;
  2071. X        q = a + strlen(a) - 1;
  2072. X      }
  2073. X    else
  2074. X#ifdef OS2
  2075. X    {
  2076. X      m = m && q >= a && tolower(*p) == tolower(*q);
  2077. X      q--;
  2078. X    }
  2079. X#else /* !OS2 */
  2080. X      m = m && q >= a && *p == *q--;
  2081. X#endif /* ?OS2 */
  2082. X  return m;
  2083. X}
  2084. X
  2085. X
  2086. int zipup(z, y)
  2087. struct zlist far *z;    /* zip entry to compress */
  2088. XFILE *y;                /* output file */
  2089. X/* Compress the file z->name into the zip entry described by *z and write
  2090. X   it to the file *y.  Determine the best method (store, shrink, or implode)
  2091. X   and use it.  Encrypt if requested.  Return an error code in the
  2092. X   ZE_ class. */
  2093. X{
  2094. X  ulg a;                /* attributes returned by filetime() */
  2095. X  char *b;              /* malloc'ed file buffer */
  2096. X  ulg c;                /* crc on uncompressed file data */
  2097. X  ftype f;              /* file to compress */
  2098. X  uch g;                /* flags returned by implode */
  2099. X  int h;                /* compression method chosen (how) */
  2100. X#ifndef NOIMPLODE
  2101. X  ulg i;                /* size of imploded data */
  2102. X#endif /* !NOIMPLODE */
  2103. X  extent k;             /* result of zread */
  2104. X  int l;                /* true if this file is a symbolic link */
  2105. X  int m;                /* method for this entry */
  2106. X  ulg n;                /* size of uncompressed file */
  2107. X  long q;               /* size returned by filetime */
  2108. X  int r;                /* temporary variable */
  2109. X  ulg s;                /* size of shrunk or compressed data */
  2110. X
  2111. X  /* Open file to zip up */
  2112. X  if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
  2113. X    return ZE_OPEN;
  2114. X  l = issymlnk(a);
  2115. X  if (l)
  2116. X    f = fbad;
  2117. X  else if ((f = zopen(z->name, fhow)) == fbad)
  2118. X    return ZE_OPEN;
  2119. X
  2120. X  /* Select method based on the suffix and the global method */
  2121. X  m = special != NULL && suffixes(z->name, special) ? STORE : method;
  2122. X
  2123. X  /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
  2124. X     number used here must be <= BSZ) */
  2125. X  if (m == BEST && q > 512)
  2126. X    m = IMPLODE;
  2127. X  if (q == 0)
  2128. X    m = STORE;
  2129. X
  2130. X  /* Make first pass on the file, computing the crc and length, and running
  2131. X     shrink and implode on it. */
  2132. X  n = 0;
  2133. X  c = updcrc((char *)NULL, 0);
  2134. X  if ((b = malloc(BSZ)) == NULL)
  2135. X    return ZE_MEM;
  2136. X  if (m == BEST || m == SHRINK)
  2137. X    if ((r = shr_setup()) != ZE_OK)
  2138. X      return r;
  2139. X    else
  2140. X      shract = 1;
  2141. X  while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  2142. X  {
  2143. X    n += k;
  2144. X    c = updcrc(b, k);
  2145. X#ifdef MINIX
  2146. X    if (l)
  2147. X      q = k;
  2148. X#endif /* MINIX */
  2149. X    if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
  2150. X    {
  2151. X      free((voidp *)b);
  2152. X      shr_clear();
  2153. X      shract = 0;
  2154. X      return r;
  2155. X    }
  2156. X    if (m == BEST)              /* free up shrink data structures */
  2157. X    {
  2158. X      if ((!l && zread(f, b, BSZ) != 0)
  2159. X#ifndef VMS
  2160. X          || n != (ulg)q
  2161. X#endif /* !VMS */
  2162. X         )
  2163. X        return ZE_READ;
  2164. X      if ((r = shr_size(&s)) != ZE_OK)
  2165. X      {
  2166. X        shr_clear();
  2167. X        shract = 0;
  2168. X        return r;
  2169. X      }
  2170. X    }
  2171. X#ifndef NOIMPLODE
  2172. X    if (m == BEST || m == IMPLODE)
  2173. X    {
  2174. X      if (!impact)
  2175. X        if ((r = imp_setup(q, level)) != ZE_OK)
  2176. X          return r;
  2177. X        else
  2178. X          impact = 1;
  2179. X      if ((r = imp_p1(b, k)) != ZE_OK)
  2180. X      {
  2181. X        free((voidp *)b);
  2182. X        imp_clear();
  2183. X        impact = 0;
  2184. X        return r;
  2185. X      }
  2186. X    }
  2187. X#endif /* !NOIMPLODE */
  2188. X    if (m == BEST || l)
  2189. X      break;
  2190. X  }
  2191. X  free((voidp *)b);
  2192. X  if (!l && zerr(f))
  2193. X    return ZE_READ;
  2194. X
  2195. X  /* Determine the best method to use */
  2196. X  g = 0;
  2197. X  if (noisy && verbose)
  2198. X    printf(" (n=%lu)", n);
  2199. X  if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
  2200. X  {
  2201. X    shr_clear();
  2202. X    shract = 0;
  2203. X    return r;
  2204. X  }
  2205. X  if (noisy && verbose && (m == BEST || m == SHRINK))
  2206. X    printf(" (s=%lu)", s);
  2207. X#ifndef NOIMPLODE
  2208. X  if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
  2209. X  {
  2210. X    imp_clear();
  2211. X    impact = 0;
  2212. X    return r;
  2213. X  }
  2214. X  if (noisy && verbose && (m == BEST || m == IMPLODE))
  2215. X    printf(" (i=%lu)", i);
  2216. X  if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
  2217. X  {
  2218. X    if (noisy)
  2219. X    {
  2220. X      printf(" (imploded %d%%)", percent(n, i));
  2221. X      fflush(stdout);
  2222. X    }
  2223. X    h = IMPLODE;
  2224. X    s = i;
  2225. X    if (m == BEST)
  2226. X    {
  2227. X      shr_clear();
  2228. X      shract = 0;
  2229. X    }
  2230. X    if (!l)
  2231. X      zclose(f);
  2232. X  }
  2233. X  else
  2234. X#endif /* !NOIMPLODE */
  2235. X  if ((m == BEST || m == SHRINK) && s < n)
  2236. X  {
  2237. X    if (noisy)
  2238. X    {
  2239. X      printf(" (shrunk %d%%)", percent(n, s));
  2240. X      fflush(stdout);
  2241. X    }
  2242. X    h = SHRINK;
  2243. X#ifndef NOIMPLODE
  2244. X    if (m == BEST)
  2245. X    {
  2246. X      imp_clear();
  2247. X      impact = 0;
  2248. X    }
  2249. X#endif /* !NOIMPLODE */
  2250. X    if (!l)
  2251. X      zclose(f);
  2252. X  }
  2253. X  else
  2254. X  {
  2255. X    if (noisy)
  2256. X    {
  2257. X      printf(" (stored 0%%)");
  2258. X      fflush(stdout);
  2259. X    }
  2260. X    h = STORE;
  2261. X    s = n;
  2262. X#ifndef NOIMPLODE
  2263. X    if (m == BEST || m == IMPLODE)
  2264. X    {
  2265. X      imp_clear();
  2266. X      impact = 0;
  2267. X    }
  2268. X#endif /* !NOIMPLODE */
  2269. X    if (m == BEST || m == SHRINK)
  2270. X    {
  2271. X      shr_clear();
  2272. X      shract = 0;
  2273. X    }
  2274. X  }
  2275. X
  2276. X#ifndef VMS
  2277. X  /* Check size (but not in VMS--variable record lengths mess it up) */
  2278. X  if (n != (ulg)q)
  2279. X    return ZE_READ;
  2280. X#endif /* !VMS */
  2281. X
  2282. X  /* Fill in header information and write local header to zip file */
  2283. X#ifdef OS2
  2284. X  if ( dosify < 2 )
  2285. X    dosify = IsFileSystemFAT(z->name);
  2286. X#endif /* OS2 */
  2287. X
  2288. X  /* (Assume ext, cext, com, and zname already filled in.) */
  2289. X  z->vem = dosify ? 11 :                /* Made under MSDOS by PKZIP 1.1 */
  2290. X#ifdef VMS
  2291. X                    0x200 + REVISION;   /* Made under VMS by this Zip */
  2292. X#else /* !VMS */
  2293. X#ifdef OS2
  2294. X                    0x600 + REVISION;   /* Made under OS/2 by this Zip */
  2295. X#else /* !OS2 */
  2296. X                    0x300 + REVISION;   /* Made under Unix by this Zip */
  2297. X#endif /* ?OS2 */
  2298. X#endif /* ?VMS */
  2299. X  z->ver = 10;                          /* Need PKUNZIP 1.0 */
  2300. X  z->flg = (ush)g;
  2301. X  if (key != NULL)
  2302. X    z->flg |= 1;
  2303. X  z->lflg = z->flg;
  2304. X  z->how = h;
  2305. X  z->crc = c;
  2306. X  z->siz = s;
  2307. X  if (key != NULL)
  2308. X    z->siz += 12;
  2309. X  z->len = n;
  2310. X  z->nam = strlen(z->zname);
  2311. X  z->dsk = 0;
  2312. X  z->att = 0;                           /* Assume they're all binary */
  2313. X  z->atx = dosify ? a & 0xff : a;       /* Attributes from filetime() */
  2314. X  if ((z->off = ftell(y)) == -1L)
  2315. X    return ZE_WRITE;
  2316. X  if ((r = putlocal(z, y)) != ZE_OK)
  2317. X    return r;
  2318. X
  2319. X  /* Write stored, shrunk, or imploded file to zip file */
  2320. X#ifndef EXPORT
  2321. X  if (key != NULL)
  2322. X    crypthead(key, z->crc, y);
  2323. X#endif /* !EXPORT */
  2324. X  n = ftell(y);                         /* Save offset for logic check */
  2325. X#ifndef NOIMPLODE
  2326. X  if (h == IMPLODE)
  2327. X  {
  2328. X    if ((r = imp_p2(y)) != ZE_OK)
  2329. X      return r;
  2330. X    imp_clear();
  2331. X    impact = 0;
  2332. X  }
  2333. X  else
  2334. X#endif /* !NOIMPLODE */
  2335. X  if (h == SHRINK)
  2336. X  {
  2337. X    if ((r = shr_p2(y)) != ZE_OK)
  2338. X      return r;
  2339. X    shr_clear();
  2340. X    shract = 0;
  2341. X  }
  2342. X  else
  2343. X  {
  2344. X    if (!l)
  2345. X      zrew(f);
  2346. X    if ((b = malloc(BSZ)) == NULL)
  2347. X      return ZE_MEM;
  2348. X    while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  2349. X    {
  2350. X      if (zfwrite(b, 1, k, y) != k)
  2351. X      {
  2352. X        free((voidp *)b);
  2353. X        return ZE_TEMP;
  2354. X      }
  2355. X      if (l)
  2356. X        break;
  2357. X    }
  2358. X    free((voidp *)b);
  2359. X    if (!l && zerr(f))
  2360. X      return ZE_READ;
  2361. X    if (!l)
  2362. X      zclose(f);
  2363. X  }
  2364. X
  2365. X  /* Check length of compressed data */
  2366. X  if (ftell(y) != n + s)
  2367. X    return ZE_LOGIC;
  2368. X
  2369. X  /* Done--clean up and leave */
  2370. X  if (noisy)
  2371. X  {
  2372. X    putchar('\n');
  2373. X    fflush(stdout);
  2374. X  }
  2375. X  return ZE_OK;
  2376. X}
  2377. X
  2378. X#endif /* !UTIL */
  2379. END_OF_FILE
  2380. if test 10409 -ne `wc -c <'zipup.c'`; then
  2381.     echo shar: \"'zipup.c'\" unpacked with wrong size!
  2382. fi
  2383. # end of 'zipup.c'
  2384. fi
  2385. echo shar: End of archive 2 \(of 7\).
  2386. cp /dev/null ark2isdone
  2387. MISSING=""
  2388. for I in 1 2 3 4 5 6 7 ; do
  2389.     if test ! -f ark${I}isdone ; then
  2390.     MISSING="${MISSING} ${I}"
  2391.     fi
  2392. done
  2393. if test "${MISSING}" = "" ; then
  2394.     echo You have unpacked all 7 archives.
  2395.     rm -f ark[1-9]isdone
  2396. else
  2397.     echo You still need to unpack the following archives:
  2398.     echo "        " ${MISSING}
  2399. fi
  2400. ##  End of shell archive.
  2401. exit 0
  2402.